
import datetime
import json
import math
from math import pi,sin,cos
import time,redis
pool_redis= redis.ConnectionPool(host='localhost',port=6379,decode_responses=True)
mesg_redis=redis.Redis(connection_pool=pool_redis)
#获取里程信息：需要的参数，(last_mesg：数据库最新的设备信息,msg_to_db：本次设备上传的数据)计算本次定位点和上次定位点的距离，返回结果，{'total_mileage':总里程,'mileage':本次里程}
#计算油耗信息，在用户设置油耗系数之后，用里程计算油耗信息，返回结果{'total_oil'：总油耗，'oil_use'：本次油耗}

def get_mileage(last_mesg,msg_to_db):
	result={}
	mileage=0
	total_mileage=0
	mesg_time=0
	lng=msg_to_db['lng']
	lat=msg_to_db['lat']
	l_lng=last_mesg['lng']
	l_lat=last_mesg['lat']
	last_mileage=last_mesg['mileage']
	last_oil=last_mesg['oil_use']
	

	if last_mileage=='0' or last_mileage==0:
		last_mileage={'total_mileage':0,'mileage':0,'time_use':0}
		last_oil={'total_oil':0,'oil_use':0}
	else:
		last_mileage=eval(last_mileage)
		last_oil=eval(last_oil)

	if l_lng==lng and l_lat==lat:
		pass
	elif float(l_lng)==0 or float(lng)==0:
		pass
	else:
		last_point=[l_lng,l_lat]
		this_point=[lng,lat]
		gps_mileage=get_distance(this_point,last_point)
		t_time=int(time.mktime(time.strptime(msg_to_db['dev_upload'], "%Y-%m-%d %H:%M:%S")))
		l_time=0
		if last_mesg['dev_upload']!='0':
			l_time=int(time.mktime(time.strptime(last_mesg['dev_upload'], "%Y-%m-%d %H:%M:%S")))
		mesg_time=t_time-l_time

		if gps_mileage/mesg_time<0.05:
			mileage=round(gps_mileage,4)


	total_mileage=last_mileage['total_mileage']+mileage
	result['mileage']=mileage
	result['total_mileage']=total_mileage
	result['time_use']=mesg_time

	oil_use=0
	total_oil=0
	if last_mesg['oil_set']!='0' and mileage!=0:
		oil_set=int(last_mesg['oil_set'])
		oil_use=round(mileage*(oil_set/100),5)
		total_oil=oil_use+last_oil['total_oil']

	result['oil_use']=oil_use
	result['total_oil']=total_oil

	return result

# 超过阈值的开始
# 1：接收到的参数不为0
# 2、接收到的参数大于设置的阈值
# 存储报警信息，添加报警开始时间
# 超过阈值的状态持续
# 1、接收到的参数大于设置的阈值
# 超过阈值的状态结束
# 1、接收到的参数小于设置的阈值
# 更新报警信息，添加报警结束时间，初始化报警存储参数

# (last_mesg：数据库最新的设备信息,
# msg_to_db：本次设备上传的数据，
# session：数据库连接,
# Alarm：报警表,
# param_name：参数字段名,
# param_set：保存设置参数的字段名,
# param_alarm：保存参数报警信息的字段名):
# 例如：超速报警，'speed','speed_limit','speed_alarm'

def get_exceed_param(lng,lat,speed,speed_set,alarm_time):
	# 超速判断,超速设置数据格式{speed_param:num,speed_status:over_speed/normal,'alarm_status':[alarm_name,alarm_time,'0']}
	speed_param=speed_set['speed_param']
	speed_status=speed_set['speed_status']
	this_status='0'

	# 给判断结果赋初值，防止速度值乱设置，无法进行比较，导致系统奔溃
	judge_result=speed_status
	try:
		judge_result=int(speed)>int(speed_param)
	except:
		print('judge_result_error',speed,speed_param)

	if judge_result==True:
		judge_result='over_speed'
	elif judge_result==False:
		judge_result='normal'

	# 如果超速状态发生变化，从正常进入超速，或者超速回复正常，进行进一步处理
	if judge_result!=speed_status:
		# 如果是超速，判断为从正常进入超速，提交报警数据
		if judge_result=='over_speed':
			#定义报警数据字典
			alarm_name=str([device_id,'over_speed',datetime.datetime.now()])
			alarm_to_db={'name':alarm_name,'device_id':device_id,
						 'location':str([lng,lat]),'content':'限速：'+speed_param+',时速：'+speed,'kind':'over_speed','handle':'no',
						 's_time':alarm_time,'e_time':'0','remark':'0'}
			# 更新围栏的报警状态信息，efence_status内容
			this_status={'speed_status':judge_result,'alarm_status':[alarm_name,alarm_time,'0']}
			# 数据提交到redis
			msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
			mesg_redis.rpush('msg_to_db',str(msg_to_db))
		# 如果为正常，判断为从超速变为正常，结束超速报警
		elif judge_result=='normal':
			alarm_status=speed_set['alarm_status']
			if alarm_status!='0':
				alarm_name=alarm_status[0]
				alarm_to_db={'name':alarm_name,'e_time':alarm_time}
				msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'update','content':alarm_to_db}
				mesg_redis.rpush('msg_to_db',str(msg_to_db))
				this_status={'speed_status':judge_result,'alarm_status':'0'}

	if this_status!='0':
		speed_set.update(this_status)


	return speed_set

#围栏报警redis取围栏数据，和本次的数据进行匹配计算
def efence_compute(compute_dynamic,efence,owner):
	print('START-----------------------------------EFENCE')
	#围栏数据格式，{efence_name:{efence_param:{efence_name:围栏1,alarm_kind:in/out/all,s_time:xxx,e_time:xxx,efence_kind:circle/polygon/rec,efence_content:[]}，efence_status:{in_out_status:in/out，alarm_status:[alarm_name,s_time,e_time]}}，efence_name:{}}
	device_id=compute_dynamic['device_id']
	lng=compute_dynamic['lng']
	lat=compute_dynamic['lat']
	alarm_time=compute_dynamic['serv_receive']
	efence=eval(efence)
	for efence_name in efence:
		efence_detail=efence[efence_name]
		alarm_kind=efence_detail['alarm_kind']
		s_time=efence_detail['s_time']
		e_time=efence_detail['e_time']
		last_inout=''
		if efence_detail.get('efence_status')!=None:
			last_inout=efence_detail['efence_status']['in_out_status']
		
		#围栏生效时间判断
		now=int(time.time())
		if s_time!='':
			s_time=int(time.mktime(time.strptime(s_time, "%Y-%m-%d %H:%M:%S")))
		if e_time!='':
			e_time=int(time.mktime(time.strptime(e_time, "%Y-%m-%d %H:%M:%S")))

		efence_judge='yes'

		if s_time!='' and e_time!='':
			if now<s_time or now>e_time:
				efence_judge='no'

		elif s_time=='' and e_time!='':
			if now>e_time:
				efence_judge='no'
		elif s_time!='' and e_time=='':
			if now<s_time:
				efence_judge='no'
		
		if efence_judge=='yes':
			#围栏的内容和围栏类型
			efence_data=efence_detail['content']
			efence_kind=efence_detail['kind']
			#获取最新设备存储的围栏报警信息
			efence_point=wgs84_bdmap([lng,lat])
			judge_result=last_inout
			this_status='0'


			#多边形围栏判断,加入try，防止计算失败导致奔溃
			if efence_kind=='polygon' or efence_kind=='rectangle':
				try:
					judge_result=poly_efence(efence_point,efence_data)
				except:
					print('polygon_error',efence_point,efence_data)

			#圆形围栏判断，防止计算失败导致奔溃
			elif efence_kind=='circle':
				try:
					circle_center=[efence_data[1]['lng'],efence_data[1]['lat']]
					compute_data=get_distance(efence_point,circle_center)
					judge_result=(compute_data)*1000<efence_data[0]
				except:
					print('circle_error',efence_point,efence_data)

			# 对围栏计算结果进行转换
			if judge_result==True:
				judge_result='in'
			elif judge_result==False:
				judge_result='out'

			# 判断上次围栏判断情况，如果初次计算，或者进出状态发生变化，进行进一步判断处理
			if last_inout=='0' or last_inout=='' or judge_result!=last_inout:
				# 进出判断的结果和进出判断报警一致的,提交报警信息至redis，
				if judge_result==alarm_kind or alarm_kind=='all':
					alarm_name=device_id+'efence_alarm'+alarm_time
					alarm_to_db={'name':alarm_name,'device_id':device_id,
								 'location':str([lng,lat]),'content':str([efence_name,judge_result]),'kind':efence_kind,'handle':'no',
								 's_time':alarm_time,'e_time':'0','remark':'0','owner':owner}
					# 更新围栏的报警状态信息，efence_status内容
					this_status={'in_out_status':judge_result,'alarm_status':[alarm_name,alarm_time,'0']}

					# 数据提交到redis
					msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
					mesg_redis.rpush('msg_to_db',str(msg_to_db))
					
				else:
					# 进出状态发生变化，进出报警类型和结果也不一样的情况，看是否存在报警记录，有的话，报警记录做结束处理，添加结束时间。
					alarm_status='0'
					if efence_detail.get('efence_status')!=None:
						alarm_status=efence_detail['efence_status']['alarm_status']
					if alarm_status!='0':
						alarm_name=alarm_status[0]
						s_alarm_time=alarm_status[1]
						alarm_to_db={'name':alarm_name,'device_id':device_id,
									 'location':str([lng,lat]),'content':str([efence_name,judge_result]),'kind':efence_kind,'handle':'auto_end',
									 's_time':s_alarm_time,'e_time':alarm_time,'remark':'0','owner':owner}
						msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'update','content':alarm_to_db}
						mesg_redis.rpush('msg_to_db',str(msg_to_db))
						this_status={'in_out_status':judge_result,'alarm_status':'0'}

			if this_status!='0':
				if efence_detail.get('efence_status')!=None:
					efence[efence_name]['efence_status'].update(this_status)
				else:
					efence[efence_name]['efence_status']={}
					efence[efence_name]['efence_status'].update(this_status)

	efence=str(efence)

	return efence


#停留超时报警
#一、上次停留状态信息，可能的状态
# 初始状态（新设备的第一条数据）,
# 开始停留
# 持续停留
# 开始移动（停留结束）
# 持续移动
#判断为初始状态，赋初值，不为初始状态，取上一次判断的状态结果，结果的status为0，上一次判读信息清零，则赋初值，开始新一轮判断计算，即对比本次的信息，判读出停留数据。

#二、本次的接收到的信息，对比上次停留，判断得出本次信息
# 停留，速度为0，
# 移动，速度不为0，

def get_stop_time(lng,lat,speed,stop_set,last_receive_time,this_receive_time):
	# 停留设置数据格式{stop_param:num,stop_time:num,stop_status:over_stop/normal/move,'alarm_status':[alarm_name,alarm_time,'0']}
	stop_param=stop_set['stop_param']
	stop_status=stop_set['stop_status']
	this_status='0'
	stop_time=0

	# 给判断结果赋初值，防止速度值乱设置，无法进行比较，导致系统奔溃
	judge_result=stop_status
	# 速度为零，累加停留时间
	if speed==0:
		this_receive_time=int(time.mktime(time.strptime(this_receive_time, "%Y-%m-%d %H:%M:%S")))
		last_receive_time=int(time.mktime(time.strptime(last_receive_time, "%Y-%m-%d %H:%M:%S")))
		stop_time=int(stop_set['stop_time'])+(this_receive_time-last_receive_time)

		try:
			judge_result=stop_time>int(stop_param)*60
		except:
			print('stop_time_error',speed,stop_param)

		if judge_result==True:
			judge_result='over_stop'
		elif judge_result==False:
			judge_result='normal'
	else:
		# 有速度，停留时间归零
		judge_result='move'

	# 停留时间更新，有速度的，停留时间为零，无速度，停留时间累加
	this_status={'stop_time':str(stop_time)}

	# 停留状态发送编号，并且停留报警参数不为零，进行进一步处理
	if judge_result!=stop_status and int(stop_param)!='0':
		# 如果是超速，判断为从正常进入超速，提交报警数据
		if judge_result=='over_stop':
			#定义报警数据字典
			alarm_name=device_id+'speed_alarm'+datetime.datetime.now()
			alarm_to_db={'name':alarm_name,'device_id':device_id,
						 'location':str([lng,lat]),'content':'停留限制：'+stop_param+',实际停留：'+str(stop_time),'kind':'over_stop','handle':'no',
						 's_time':this_receive_time,'e_time':'0','remark':'0','owner':owner}
			# 更新停留的报警状态信息，efence_status内容
			this_status={'stop_status':judge_result,'stop_time':stop_time,'alarm_status':[alarm_name,this_receive_time,'0']}
			# 数据提交到redis
			msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
			mesg_redis.rpush('msg_to_db',str(msg_to_db))
		# 移动状态，结束停留报警
		elif judge_result=='move':
			alarm_status=stop_set['alarm_status']
			if alarm_status!='0':
				alarm_name=alarm_status[0]
				alarm_to_db={'name':alarm_name,'e_time':this_receive_time}
				msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'update','content':alarm_to_db}
				mesg_redis.rpush('msg_to_db',str(msg_to_db))
				this_status={'stop_status':judge_result,'alarm_status':'0','stop_time':'0'}

	stop_set.update(this_status)

	return stop_set

# 计算心率报警
# 复杂模式，记录每个报警数据的生命周期，开始，持续，结束，在alarm报警报表，device的param_set的heart_set字段，需要做数据同步，如果用户手动处理报警，也需要在两个地方做数据同步。
def heart_alarm_compute_c(compute_dynamic,param_set,status,owner):
	# 心率报警数据格式heart_set{heart_hight:xx,heart_low:xx,hh_status:{judge:xx,alarm:[alarm_name,alarm_time,heart_rate]},hl_status:{judge:xx,alarm:[alarm_name,alarm_time,heart_rate]}}
	if param_set['heart_set']!='0':
		heart_set_detail=param_set['heart_set']
		lng=compute_dynamic['lng']
		lat=compute_dynamic['lat']
		alarm_time=compute_dynamic['serv_receive']
		this_status='0'
		if isinstance(heart_set_detail,dict)==True:
			heart_rate=compute_dynamic['heart_rate']
			alarm_time=compute_dynamic['serv_receive']
			heart_alarm_kind=''
			if 'heart_hight' in heart_set_detail:
				if int(heart_set_detail['heart_hight'])!=0:
					if int(heart_rate)>int(heart_set_detail['heart_hight']):
						heart_alarm_kind='heart_hight'

			if 'heart_low' in heart_set_detail:
				if int(heart_set_detail['heart_low'])!=0:
					if int(heart_rate)<int(heart_set_detail['heart_low']):
						heart_alarm_kind='heart_low'

			last_judge=''
			if heart_alarm_kind!='':
				# 获取上次的报警情况，是否有报警
				status_dict={'heart_hight':'hh_status','heart_low':'hl_status'}
				if heart_set_detail.get(status_dict[heart_alarm_kind])!=None:
					last_judge=heart_set_detail.get(status_dict[heart_alarm_kind])['judge']

				if last_judge=='' or last_judge=='normal':
					alarm_to_db={'name':heart_alarm_kind+msg_to_db['device_id']+str(time.mktime(time.strptime(alarm_time, "%Y-%m-%d %H:%M:%S"))),'device_id':msg_to_db['device_id'],'location':str([lng,lat]),'alarm_content':'0',
				  'kind':heart_alarm_kind,'handle':'no','s_time':alarm_time,'e_time':'0','remark':'0','owner':owner}
				  # 数据提交到redis
					msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
					mesg_redis.rpush('msg_to_db',str(msg_to_db))
					this_status={status_dict[heart_alarm_kind]:{'judge':'alarm','alarm':[alarm_name,alarm_time,heart_rate]}}
					heart_set_detail.update(this_status)
			else:
				if heart_set_detail.get('hh_status')!=None:
					last_judge=heart_set_detail.get('hh_status')['judge']
					if last_judge=='alarm':
						alarm_name=heart_set_detail.get('hh_status')[alarm][0]
						alarm_to_db={'name':alarm_name,'e_time':alarm_time}
						msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'update','content':alarm_to_db}
						mesg_redis.rpush('msg_to_db',str(msg_to_db))
						this_status={'hh_status':{'judge':'normal','alarm':'0'}}
						heart_set_detail.update(this_status)

				if heart_set_detail.get('hl_status')!=None:
					last_judge=heart_set_detail.get('hl_status')['judge']
					if last_judge=='alarm':
						alarm_name=heart_set_detail.get('hl_status')[alarm][0]
						alarm_to_db={'name':alarm_name,'e_time':alarm_time}
						msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'update','content':alarm_to_db}
						mesg_redis.rpush('msg_to_db',str(msg_to_db))
						this_status={'hl_status':{'judge':'normal','alarm':'0'}}
						heart_set_detail.update(this_status)

	param_set['heart_set']=heart_set_detail
	return param_set

# 计算心率报警
# 简单模式，存储每次的报警数据，每次对比超出设置的心率报警值，马上在alarm报表进行记录，用户可以在报警报表进行处理
def heart_alarm_compute(compute_dynamic,param_set,status,owner):
	# 心率报警数据格式heart_set{heart_hight:xx,heart_low:xx}
	if param_set['heart_set']!='0':
		location=compute_dynamic['location']
		heart_set_detail=param_set['heart_set']
		lng=compute_dynamic['lng']
		lat=compute_dynamic['lat']
		alarm_time=compute_dynamic['serv_receive']
		this_status='0'
		device_id=compute_dynamic['device_id']
		if isinstance(heart_set_detail,dict)==True:
			heart_rate=compute_dynamic['heart_rate']
			alarm_time=compute_dynamic['serv_receive']
			heart_alarm_kind=''
			if 'heart_hight' in heart_set_detail:
				if int(heart_set_detail['heart_hight'])!=0:
					if int(heart_rate)>int(heart_set_detail['heart_hight']):
						heart_alarm_kind='heart_hight'

			if 'heart_low' in heart_set_detail:
				if int(heart_set_detail['heart_low'])!=0:
					if int(heart_rate)<int(heart_set_detail['heart_low']):
						heart_alarm_kind='heart_low'


			if heart_alarm_kind!='':
				alarm_name=device_id+heart_alarm_kind+alarm_time
				alarm_to_db={'name':alarm_name,'device_id':device_id,'location':location,'content':heart_rate,
			  'kind':heart_alarm_kind,'handle':'no','s_time':alarm_time,'e_time':'0','remark':'0','owner':owner}
			  # 数据提交到redis
				msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
				mesg_redis.rpush('msg_to_db',str(msg_to_db))

				# 在设备状态字段，添加该报警信息
				status.append(heart_alarm_kind)


	return status




# 计算血压报警，每次比对血压数据和设置的报警阈值，超出即报警，在alarm报表存储，在status里面存储改报警状态
def blood_alarm_compute(compute_dynamic,param_set,status,owner):
	
	if param_set['blood_set']!='0':
		location=compute_dynamic['location']
		blood_pres=eval(compute_dynamic['blood_pres'])
		blood_set=param_set['blood_set']
		lng=compute_dynamic['lng']
		lat=compute_dynamic['lat']
		alarm_time=compute_dynamic['serv_receive']
		device_id=compute_dynamic['device_id']
		if isinstance(blood_pres,dict)==True and isinstance(blood_set,dict)==True:
			blood_alarm_kind=''
			if 'l_pres_low' in blood_set:
				if int(blood_set['l_pres_low'])!=0:
					if int(blood_pres['l_pres'])<int(blood_set['l_pres_low']):
						blood_alarm_kind='l_pres_low'
			if 'l_pres_hight' in blood_set:
				if int(blood_set['l_pres_hight'])!=0:
					if int(blood_pres['l_pres'])>int(blood_set['l_pres_hight']):
						blood_alarm_kind='l_pres_hight'

			if blood_alarm_kind!='':
				alarm_name=device_id+blood_alarm_kind+alarm_time
				alarm_to_db={'name':alarm_name,'device_id':device_id,'location':location,'content':blood_pres['l_pres'],
				  'kind':blood_alarm_kind,'handle':'no','s_time':alarm_time,'e_time':'0','remark':'0','owner':owner}
			  # 数据提交到redis
				msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
				mesg_redis.rpush('msg_to_db',str(msg_to_db))

				# 在设备状态字段，添加该报警信息
				status.append(blood_alarm_kind)

			blood_alarm_kind=''
			if 'h_pres_low' in blood_set:
				if int(blood_set['h_pres_low'])!=0:
					if int(blood_pres['h_pres'])<int(blood_set['h_pres_low']):
						blood_alarm_kind='h_pres_low'
			if 'h_pres_hight' in blood_set:
				if int(blood_set['h_pres_hight'])!=0:
					if int(blood_pres['h_pres'])>int(blood_set['h_pres_hight']):
						blood_alarm_kind='h_pres_hight'

			if blood_alarm_kind!='':
				alarm_name=device_id+blood_alarm_kind+alarm_time
				alarm_to_db={'name':alarm_name,'device_id':device_id,'location':location,'content':blood_pres['h_pres'],
				  'kind':blood_alarm_kind,'handle':'no','s_time':alarm_time,'e_time':'0','remark':'0','owner':owner}
			 	# 数据提交到redis
				msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
				mesg_redis.rpush('msg_to_db',str(msg_to_db))

				# 在设备状态字段，添加该报警信息
				status.append(heart_alarm_kind)

	return status


# 计算血压报警，每次比对血压数据和设置的报警阈值，超出即报警，在alarm报表存储，在status里面存储改报警状态
def other_alarm_compute(compute_dynamic,status,owner):
	device_id=compute_dynamic['device_id']
	location=compute_dynamic['location']
	# lng=compute_dynamic['lng']
	# lat=compute_dynamic['lat']
	alarm_time=compute_dynamic['serv_receive']
	# 报警数据存库
	alarm_mesg=eval(compute_dynamic['sos_alarm'])
	for x in alarm_mesg:
		alarm_name=device_id+x+alarm_time
		alarm_to_db={'name':alarm_name,'device_id':device_id,
					 'location':location,'content':x,'handle':'no',
					 's_time':alarm_time,'e_time':'0','remark':'0','kind':x,'owner':owner}
		# 数据提交到redis
		msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
		mesg_redis.rpush('msg_to_db',str(msg_to_db))

		# 在设备状态字段，添加该报警信息
		status.append(x)

	return status

# 静止时长报警计算，2020.9.15 吕康宁
def stop_alarm_compute(compute_dynamic,param_set,status,owner):
	if param_set['stop_rate']!='0':
		stop_rate=param_set['stop_rate']
		if isinstance(stop_rate,dict):
			stop_rate=int(stop_rate['stop_rate'])
			location=compute_dynamic['location']
			stop_time=int(compute_dynamic['stop_time'])
			alarm_time=compute_dynamic['serv_receive']
			device_id=compute_dynamic['device_id']

			if stop_time>stop_rate*60:
				alarm_name=device_id+'stop_alarm'+alarm_time
				alarm_to_db={'name':alarm_name,'device_id':device_id,
							 'location':location,'content':stop_time,'handle':'no',
							 's_time':alarm_time,'e_time':'0','remark':'0','kind':'stop_alarm','owner':owner}
				# 数据提交到redis
				msg_to_db={'table_name':'tracker_app_alarm','handle_kind':'add','content':alarm_to_db}
				mesg_redis.rpush('msg_to_db',str(msg_to_db))

				# 在设备状态字段，添加该报警信息
				status.append('stop_alarm')

	return status
	

#点位置是否在多边形里面的的判断函数

def poly_efence(p,efence_data):

	efence_data=efence_data
	efencepoly=[]
	efencepolys=[]
	hard_point=[]
	hard_points=[]
	for x in efence_data:
		hard_point.append(x['lng'])
		hard_point.append(x['lat'])
		if len(hard_point)==2:
			efencepoly.append(hard_point)
			hard_point=[]
	for x in range(len(efencepoly)-1):
		hard_points.append(efencepoly[x])
		hard_points.append(efencepoly[x+1])
		efencepolys.append(hard_points)
		hard_points=[]
		if x==len(efencepoly)-2:
			hard_points.append(efencepoly[x])
			hard_points.append(efencepoly[0])
			efencepolys.append(hard_points)
	#print('efencepolys:',efencepolys)
	def isRayIntersectsSegment(poi,s_poi,e_poi): #[x,y] [lng,lat]
		#输入：判断点，边起点，边终点，都是[lng,lat]格式数组
		if s_poi[1]==e_poi[1]: #排除与射线平行、重合，线段首尾端点重合的情况
			return False
		if s_poi[1]>poi[1] and e_poi[1]>poi[1]: #线段在射线上边
			return False
		if s_poi[1]<poi[1] and e_poi[1]<poi[1]: #线段在射线下边
			return False
		if s_poi[1]==poi[1] and e_poi[1]>poi[1]: #交点为下端点，对应spoint
			return False
		if e_poi[1]==poi[1] and s_poi[1]>poi[1]: #交点为下端点，对应epoint
			return False
		if s_poi[0]<poi[0] and e_poi[1]<poi[1]: #线段在射线左边
			return False

		xseg=e_poi[0]-(e_poi[0]-s_poi[0])*(e_poi[1]-poi[1])/(e_poi[1]-s_poi[1]) #求交
		if xseg<poi[0]: #交点在射线起点的左侧
			return False
		return True  #排除上述情况之后


	def isPoiWithinPoly(poi,poly):
		#输入：点，多边形三维数组
		#poly=[[[x1,y1],[x2,y2],……,[xn,yn],[x1,y1]],[[w1,t1],……[wk,tk]]] 三维数组

		#可以先判断点是否在外包矩形内 
		#if not isPoiWithinBox(poi,mbr=[[0,0],[180,90]]): return False
		#但算最小外包矩形本身需要循环边，会造成开销，本处略去
		sinsc=0 #交点个数
		for epoly in poly: #循环每条边的曲线->each polygon 是二维数组[[x1,y1],…[xn,yn]]
			for i in range(len(epoly)-1): #[0,len-1]
				s_poi=epoly[i]
				e_poi=epoly[i+1]
				if isRayIntersectsSegment(poi,s_poi,e_poi):
					sinsc+=1 #有交点就加1

		return True if sinsc%2==1 else  False
	#print(isPoiWithinPoly(p,efencepolys))
	result=isPoiWithinPoly(p,efencepolys)

	return result

#两点经纬度计算距离函数
def get_distance(point1,point2):
	lat1=point1[1]
	lat2=point2[1]
	lng1=point1[0]
	lng2=point2[0]

	EARTH_REDIUS = 6378.137

	def rad(d):
		return d * pi / 180.0

	radLat1 = rad(lat1)
	radLat2 = rad(lat2)
	lat_a = radLat1 - radLat2
	lng_b = rad(lng1) - rad(lng2)
	result_s = 2 * math.asin(math.sqrt(math.pow(sin(lat_a/2), 2) + cos(radLat1) * cos(radLat2) * math.pow(sin(lng_b/2), 2)))
	result_s = result_s * EARTH_REDIUS

	return result_s

#wgs84坐标系转换成百度坐标系计算函数
def wgs84_bdmap(wpoint):

	pi = 3.14159265358979324;
	a = 6378245.0;
	ee = 0.00669342162296594323;
	x_pi = 3.14159265358979324 * 3000.0 / 180.0;

	def wgs2bd(lat, lon): 
		   _wgs2gcj = wgs2gcj(lat, lon);
		   _gcj2bd = gcj2bd(_wgs2gcj[0], _wgs2gcj[1]);
		   return _gcj2bd;
	

	def gcj2bd(lat, lon):
		   x = lon
		   y = lat
		   z = math.sqrt(x * x + y * y) + 0.00002 * math.sin(y * x_pi);
		   theta = math.atan2(y, x) + 0.000003 * math.cos(x * x_pi);
		   bd_lon = z * math.cos(theta) + 0.0065;
		   bd_lat = z * math.sin(theta) + 0.006;
		   return [ bd_lat, bd_lon ];
	

	def bd2gcj(lat, lon): 
		   x = lon - 0.0065
		   y = lat - 0.006
		   z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * x_pi);
		   theta = math.atan2(y, x) - 0.000003 * math.cos(x * x_pi);
		   gg_lon = z * math.cos(theta);
		   gg_lat = z * math.sin(theta);
		   return [ gg_lat, gg_lon ];
	

	def wgs2gcj(lat, lon): 
		   dLat = transformLat(lon - 105.0, lat - 35.0);
		   dLon = transformLon(lon - 105.0, lat - 35.0);
		   radLat = lat / 180.0 * pi;
		   magic = math.sin(radLat);
		   magic = 1 - ee * magic * magic;
		   sqrtMagic = math.sqrt(magic);
		   dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
		   dLon = (dLon * 180.0) / (a / sqrtMagic * math.cos(radLat) * pi);
		   mgLat = lat + dLat;
		   mgLon = lon + dLon;
		   return [ mgLat, mgLon ];
	

	def transformLat(lat, lon): 
		   ret = -100.0 + 2.0 * lat + 3.0 * lon + 0.2 * lon * lon + 0.1 * lat * lon + 0.2 * math.sqrt(abs(lat));
		   ret += (20.0 * math.sin(6.0 * lat * pi) + 20.0 * math.sin(2.0 * lat * pi)) * 2.0 / 3.0;
		   ret += (20.0 * math.sin(lon * pi) + 40.0 * math.sin(lon / 3.0 * pi)) * 2.0 / 3.0;
		   ret += (160.0 * math.sin(lon / 12.0 * pi) + 320 * math.sin(lon * pi  / 30.0)) * 2.0 / 3.0;
		   return ret;
	

	def transformLon(lat, lon): 
		   ret = 300.0 + lat + 2.0 * lon + 0.1 * lat * lat + 0.1 * lat * lon + 0.1 * math.sqrt(abs(lat));
		   ret += (20.0 * math.sin(6.0 * lat * pi) + 20.0 * math.sin(2.0 * lat * pi)) * 2.0 / 3.0;
		   ret += (20.0 * math.sin(lat * pi) + 40.0 * math.sin(lat / 3.0 * pi)) * 2.0 / 3.0;
		   ret += (150.0 * math.sin(lat / 12.0 * pi) + 300.0 * math.sin(lat / 30.0 * pi)) * 2.0 / 3.0;
		   return ret;
	wgs2bd=wgs2bd(wpoint[1],wpoint[0])
	wgs2bd.reverse()
	return wgs2bd